home *** CD-ROM | disk | FTP | other *** search
- /* 3D animation program to view a cube as it rotates in
- mode X. The viewpoint is fixed at the origin (0,0,0) of world
- space, looking in the direction of increasingly negative Z. A
- right-handed coordinate system is used throughout.
- All C code tested with Borland C++ 2.0 in C compilation mode */
- #include <conio.h>
- #include <dos.h>
- #include <math.h>
- #include "polygon.h"
-
- #define ROTATION (M_PI / 30.0) /* rotate by 6 degrees at a time */
-
- /* Base offset of page to which to draw */
- unsigned int CurrentPageBase = 0;
- /* Clip rectangle; clips to the screen */
- int ClipMinX=0, ClipMinY=0;
- int ClipMaxX=SCREEN_WIDTH, ClipMaxY=SCREEN_HEIGHT;
- /* Rectangle specifying extent to be erased in each page */
- struct Rect EraseRect[2] = { {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT},
- {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT} };
- static unsigned int PageStartOffsets[2] =
- {PAGE0_START_OFFSET,PAGE1_START_OFFSET};
- int DisplayedPage, NonDisplayedPage;
- /* Transformation from cube's object space to world space. Initially
- set up to perform no rotation and to move the cube into world
- space -100 units away from the origin down the Z axis. Given the
- viewing point, -100 down the Z axis means 100 units away in the
- direction of view. The program dynamically changes both the
- translation and the rotation. */
- static double CubeWorldXform[4][4] = {
- {1.0, 0.0, 0.0, 0.0},
- {0.0, 1.0, 0.0, 0.0},
- {0.0, 0.0, 1.0, -100.0},
- {0.0, 0.0, 0.0, 1.0} };
- /* Transformation from world space into view space. Because in this
- application the view point is fixed at the origin of world space,
- looking down the Z axis in the direction of increasing Z, view space is
- identical to world space, and this is the identity matrix */
- static double WorldViewXform[4][4] = {
- {1.0, 0.0, 0.0, 0.0},
- {0.0, 1.0, 0.0, 0.0},
- {0.0, 0.0, 1.0, 0.0},
- {0.0, 0.0, 0.0, 1.0}
- };
- /* All vertices in the cube */
- static struct Point3 CubeVerts[] = {
- {15,15,15,1},{15,15,-15,1},{15,-15,15,1},{15,-15,-15,1},
- {-15,15,15,1},{-15,15,-15,1},{-15,-15,15,1},{-15,-15,-15,1}};
- /* Vertices after transformation */
- static struct Point3
- XformedCubeVerts[sizeof(CubeVerts)/sizeof(struct Point3)];
- /* Vertices after projection */
- static struct Point3
- ProjectedCubeVerts[sizeof(CubeVerts)/sizeof(struct Point3)];
- /* Vertices in screen coordinates */
- static struct Point
- ScreenCubeVerts[sizeof(CubeVerts)/sizeof(struct Point3)];
- /* Vertex indices for individual faces */
- static int Face1[] = {1,3,2,0};
- static int Face2[] = {5,7,3,1};
- static int Face3[] = {4,5,1,0};
- static int Face4[] = {3,7,6,2};
- static int Face5[] = {5,4,6,7};
- static int Face6[] = {0,2,6,4};
- /* List of cube faces */
- static struct Face CubeFaces[] = {{Face1,4,15},{Face2,4,14},
- {Face3,4,12},{Face4,4,11},{Face5,4,10},{Face6,4,9}};
- /* Master description for cube */
- static struct Object Cube = {sizeof(CubeVerts)/sizeof(struct Point3),
- CubeVerts, XformedCubeVerts, ProjectedCubeVerts, ScreenCubeVerts,
- sizeof(CubeFaces)/sizeof(struct Face), CubeFaces};
-
- void main() {
- int Done = 0, RecalcXform = 1;
- double WorkingXform[4][4];
- union REGS regset;
-
- /* Set up the initial transformation */
- Set320x240Mode(); /* set the screen to mode X */
- ShowPage(PageStartOffsets[DisplayedPage = 0]);
- /* Keep transforming the cube, drawing it to the undisplayed page,
- and flipping the page to show it */
- do {
- /* Regenerate the object->view transformation and
- retransform/project if necessary */
- if (RecalcXform) {
- ConcatXforms(WorldViewXform, CubeWorldXform, WorkingXform);
- /* Transform and project all the vertices in the cube */
- XformAndProjectPoints(WorkingXform, &Cube);
- RecalcXform = 0;
- }
- CurrentPageBase = /* select other page for drawing to */
- PageStartOffsets[NonDisplayedPage = DisplayedPage ^ 1];
- /* Clear the portion of the non-displayed page that was drawn
- to last time, then reset the erase extent */
- FillRectangleX(EraseRect[NonDisplayedPage].Left,
- EraseRect[NonDisplayedPage].Top,
- EraseRect[NonDisplayedPage].Right,
- EraseRect[NonDisplayedPage].Bottom, CurrentPageBase, 0);
- EraseRect[NonDisplayedPage].Left =
- EraseRect[NonDisplayedPage].Top = 0x7FFF;
- EraseRect[NonDisplayedPage].Right =
- EraseRect[NonDisplayedPage].Bottom = 0;
- /* Draw all visible faces of the cube */
- DrawVisibleFaces(&Cube);
- /* Flip to display the page into which we just drew */
- ShowPage(PageStartOffsets[DisplayedPage = NonDisplayedPage]);
- while (kbhit()) {
- switch (getch()) {
- case 0x1B: /* Esc to exit */
- Done = 1; break;
- case 'A': case 'a': /* away (-Z) */
- CubeWorldXform[2][3] -= 3.0; RecalcXform = 1; break;
- case 'T': /* towards (+Z). Don't allow to get too */
- case 't': /* close, so Z clipping isn't needed */
- if (CubeWorldXform[2][3] < -40.0) {
- CubeWorldXform[2][3] += 3.0;
- RecalcXform = 1;
- }
- break;
- case '4': /* rotate clockwise around Y */
- AppendRotationY(CubeWorldXform, -ROTATION);
- RecalcXform=1; break;
- case '6': /* rotate counterclockwise around Y */
- AppendRotationY(CubeWorldXform, ROTATION);
- RecalcXform=1; break;
- case '8': /* rotate clockwise around X */
- AppendRotationX(CubeWorldXform, -ROTATION);
- RecalcXform=1; break;
- case '2': /* rotate counterclockwise around X */
- AppendRotationX(CubeWorldXform, ROTATION);
- RecalcXform=1; break;
- case 0: /* extended code */
- switch (getch()) {
- case 0x3B: /* rotate counterclockwise around Z */
- AppendRotationZ(CubeWorldXform, ROTATION);
- RecalcXform=1; break;
- case 0x3C: /* rotate clockwise around Z */
- AppendRotationZ(CubeWorldXform, -ROTATION);
- RecalcXform=1; break;
- case 0x4B: /* left (-X) */
- CubeWorldXform[0][3] -= 3.0; RecalcXform=1; break;
- case 0x4D: /* right (+X) */
- CubeWorldXform[0][3] += 3.0; RecalcXform=1; break;
- case 0x48: /* up (+Y) */
- CubeWorldXform[1][3] += 3.0; RecalcXform=1; break;
- case 0x50: /* down (-Y) */
- CubeWorldXform[1][3] -= 3.0; RecalcXform=1; break;
- default:
- break;
- }
- break;
- default: /* any other key to pause */
- getch(); break;
- }
- }
- } while (!Done);
- /* Return to text mode and exit */
- regset.x.ax = 0x0003; /* AL = 3 selects 80x25 text mode */
- int86(0x10, ®set, ®set);
- }